const Item = require("../models/itemModel");
const Warehouse = require("../models/warehouseModel");
const Category = require("../models/categoryModel"); 
const Tax = require("../models/taxModel");
const Unit = require("../models/unitModel");
const Sale = require("../models/Sales");

// Create a new item with proper validations and then return the populated item
exports.createItem = async (req, res) => {
  try {
    const {
      itemCode,
      itemName,
      brand,
      subCategory, 
      category,    
      itemGroup,
      unit,
      sku,
      hsn,
      barcode,
      alertQuantity,
      description,
      discountType,
      discount,
      priceWithoutTax,
      purchasePrice,
      salesPrice,
      tax,
      profitMargin,
      mrp,
      expiryDate,
      warehouse,
      openingStock,
      itemImage,
    } = req.body;
    
    // Validate category and subCategory
    const categoryDoc = await Category.findById(category).populate("subCategories", "_id");
    if (!categoryDoc) {
      return res.status(400).json({ success: false, message: "Invalid category" });
    }

    if (categoryDoc.subCategories && categoryDoc.subCategories.length > 0) {
      const validSubCategory = categoryDoc.subCategories.some(subCat => 
        subCat._id.toString() === subCategory
      );
      if (!validSubCategory) {
        return res.status(400).json({
          success: false,
          message: "Invalid subCategory for the selected category"
        });
      }
    }

    const newItem = new Item({
      itemCode,
      itemName,
      brand,
      subCategory, 
      category,   
      itemGroup,
      unit,
      sku,
      hsn,
      barcode,
      alertQuantity,
      description,
      discountType,
      discount,
      priceWithoutTax,
      purchasePrice,
      salesPrice,
      tax,
      profitMargin,
      mrp,
      expiryDate,
      warehouse,
      openingStock,
      itemImage,
    });
    
    await newItem.save();
    // Optionally populate the references before sending the response.
    const populatedItem = await Item.findById(newItem._id)
      .populate("warehouse", "warehouseName location")
      .populate("category", "name description")
      .populate("subCategory", "name description")
      .populate("brand", "brandName description")
      .populate("tax", "taxName taxPercentage")
      .populate("unit", "unitName");

    return res.status(201).json({
      success: true,
      message: "Item created successfully",
      data: populatedItem,
    });
  } catch (error) {
    return res.status(500).json({ success: false, message: error.message });
  }
};

// Get all items with full details, populating references for warehouse, category, subCategory, brand, tax, and unit
exports.getAllItems = async (req, res) => {
  try {
    const items = await Item.find()
      .populate("warehouse", "warehouseName location")
      .populate("category", "name description")
      .populate("subCategory", "name description")
      .populate("brand", "brandName description")
      .populate("tax", "taxName taxPercentage")
      .populate("unit", "unitName");
    return res.status(200).json({ success: true, data: items });
  } catch (error) {
    return res.status(500).json({ success: false, message: error.message });
  }
};

// Get item summaries (only selected fields) with warehouse and category populated
exports.getItemSummaries = async (req, res) => {
  try {
    const items = await Item.find()
      .select("itemImage itemName mrp salesPrice openingStock category description")
      .populate("warehouse", "warehouseName location")
      .populate("category", "name description");
    return res.status(200).json({ success: true, data: items });
  } catch (error) {
    return res.status(500).json({ success: false, message: error.message });
  }
};

// Get related/similar items based on category (excluding the main item)
exports.getRelatedItems = async (req, res) => {
  try {
    const mainItemId = req.params.id;
    const mainItem = await Item.findById(mainItemId);
    if (!mainItem) {
      return res.status(404).json({ success: false, message: "Item not found" });
    }
    const relatedItems = await Item.find({
      category: mainItem.category,
      _id: { $ne: mainItem._id }
    })
      .limit(4)
      .select("itemImage itemName mrp salesPrice category description")
      .populate("warehouse", "warehouseName location")
      .populate("category", "name description");
    return res.status(200).json({ success: true, data: relatedItems });
  } catch (error) {
    console.error("Error in getRelatedItems:", error);
    return res.status(500).json({ success: false, message: error.message });
  }
};

// Get an item by ID with warehouse and category populated
exports.getItemById = async (req, res) => {
  try {
    const item = await Item.findById(req.params.id)
      .populate("warehouse", "warehouseName location")
      .populate("category", "name description")
      .populate("tax", "taxName taxPercentage")
      .populate("unit", "unitName");
    if (!item) {
      return res.status(404).json({ success: false, message: "Item not found" });
    }
    return res.status(200).json({ success: true, data: item });
  } catch (error) {
    return res.status(500).json({ success: false, message: error.message });
  }
};

// Update an item and return the updated document with populated fields
exports.updateItem = async (req, res) => {
  try {
    const updatedItem = await Item.findByIdAndUpdate(req.params.id, req.body, {
      new: true,
    })
      .populate("warehouse", "warehouseName location")
      .populate("category", "name description")
      .populate("tax", "taxName taxPercentage")
      .populate("unit", "unitName");
    if (!updatedItem) {
      return res.status(404).json({ success: false, message: "Item not found" });
    }
    return res.status(200).json({
      success: true,
      message: "Item updated successfully",
      data: updatedItem,
    });
  } catch (error) {
    return res.status(500).json({ success: false, message: error.message });
  }
};

// Delete an item
exports.deleteItem = async (req, res) => {
  try {
    const deletedItem = await Item.findByIdAndDelete(req.params.id);
    if (!deletedItem) {
      return res.status(404).json({ success: false, message: "Item not found" });
    }
    return res.status(200).json({ success: true, message: "Item deleted successfully" });
  } catch (error) {
    return res.status(500).json({ success: false, message: error.message });
  }
};

// Get items near a location (from nearby stores)
exports.getItemsNearLocation = async (req, res) => {
  try {
    const { latitude, longitude, maxDistance } = req.query;
    if (!latitude || !longitude) {
      return res.status(400).json({
        success: false,
        message: "latitude and longitude query parameters are required",
      });
    }
    
    const lat = parseFloat(latitude);
    const lng = parseFloat(longitude);
    const distance = maxDistance ? parseInt(maxDistance) : 5000;

    // Find nearby warehouses using the GeoJSON location field
    const warehouses = await Warehouse.find({
      location: {
        $near: {
          $geometry: { type: "Point", coordinates: [lng, lat] },
          $maxDistance: distance,
        },
      },
    }).select("_id");

    if (!warehouses.length) {
      return res.status(200).json({ success: true, data: [] });
    }

    const warehouseIds = warehouses.map(warehouse => warehouse._id);

    // Find items whose warehouse is in the list of nearby warehouse IDs
    const items = await Item.find({
      warehouse: { $in: warehouseIds }
    })
      .select("itemImage itemName mrp salesPrice openingStock category description")
      .populate("warehouse", "warehouseName location")
      .populate("category", "name description");
    
    return res.status(200).json({ success: true, data: items });
  } catch (error) {
    console.error("Error in getItemsNearLocation:", error);
    return res.status(500).json({ success: false, message: error.message });
  }
};

exports.getTopTrendingItems = async (req, res) => {
  const limit = parseInt(req.query.limit) || 10;

  try {
    const trendingItems = await Sale.aggregate([
      { $unwind: "$items" },
      { 
        $group: { 
          _id: "$items.item",    // corrected from "items.itemId" to "items.item"
          totalSold: { $sum: "$items.quantity" } 
        } 
      },
      { 
        $lookup: { 
          from: "items", 
          localField: "_id", 
          foreignField: "_id", 
          as: "itemDetails" 
        } 
      },
      { $unwind: "$itemDetails" },
      { 
        $project: { 
          itemName: "$itemDetails.itemName", 
          totalSold: 1, 
          salesPrice: "$itemDetails.salesPrice",
          itemCode: "$itemDetails.itemCode",
          itemImage: "$itemDetails.itemImage"
        } 
      },
      { $sort: { totalSold: -1 } },
      { $limit: limit }
    ]);

    res.status(200).json({ success: true, data: trendingItems });
  } catch (error) {
    res.status(500).json({ success: false, message: error.message });
  }
};

exports.getLowStockItems = async (req, res) => {
  const threshold = parseInt(req.query.threshold) || 10;

  try {
    const items = await Item.find({ openingStock: { $lte: threshold } })
      .select("itemName openingStock alertQuantity")
      .populate("category", "name")
      .populate("brand", "brandName");

    res.status(200).json({ success: true, data: items });
  } catch (error) {
    res.status(500).json({ success: false, message: error.message });
  }
};

// Get items by category ID
exports.getItemsByCategory = async (req, res) => {
  try {
    const categoryId = req.params.categoryId;

    const items = await Item.find({ category: categoryId })
      .populate("warehouse", "warehouseName location")
      .populate("category", "name description")
      .populate("brand", "brandName description")
      .populate("tax", "taxName taxPercentage")
      .populate("unit", "unitName");

    return res.status(200).json({ success: true, data: items });
  } catch (error) {
    return res.status(500).json({ success: false, message: error.message });
  }
};
